package com.sw.c.filter;

import com.sw.c.config.SystemParams;
import com.sw.c.utils.JwtTokenUtil;
import com.sw.c.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDetailsService userDetailsService;

    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private RedisUtils redisUtils;

    @Autowired
    private SystemParams systemParams;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        List<String> whiteListPaths = systemParams.getWhiteListPaths();
        RequestMatcher[] matchers = whiteListPaths.stream()
                .map(AntPathRequestMatcher::new)
                .collect(Collectors.toList())
                .toArray(new RequestMatcher[0]);
        OrRequestMatcher orRequestMatcher = new OrRequestMatcher(matchers);

        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 使用配置文件中的白名单路径
                .requestMatchers(orRequestMatcher).permitAll()
                .anyRequest().authenticated();

        // 添加JWT过滤器，仅在非白名单路径上应用
        http.addFilter(new CustomJwtAuthorizationFilter(authenticationManager(), jwtTokenUtil, redisUtils, systemParams, orRequestMatcher));
    }
}

class CustomJwtAuthorizationFilter extends JwtAuthorizationFilter {

    private final RequestMatcher orRequestMatcher;

    public CustomJwtAuthorizationFilter(org.springframework.security.authentication.AuthenticationManager authenticationManager,
                                        JwtTokenUtil jwtTokenUtil,
                                        RedisUtils redisUtils,
                                        SystemParams systemParams,
                                        RequestMatcher orRequestMatcher) {
        super(authenticationManager, jwtTokenUtil, redisUtils, systemParams);
        this.orRequestMatcher = orRequestMatcher;
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        return orRequestMatcher.matches(request);
    }
}



